﻿using System;
using System.Windows.Forms;
using DSkin.Forms;
using Fiddler;
using System.Xml;
using System.Net;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.Text;

namespace iFiddlerX
{
    /// <summary>
    /// iFiddlerX By iRabbit
    /// </summary>
    public partial class IFiddlerMainForm : DSkinForm
    {
        #region 主窗口初始化
        public IFiddlerMainForm()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 关闭按钮设为隐藏
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void IFiddlerMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            Hide();
        }

        /// <summary>
        /// 载入窗口事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void IFiddlerMainForm_Load(object sender, EventArgs e)
        {
            Text = IRabbit.Title + " - " + IRabbit.Version;//命名标题及版本号
            ShowLocalIpAndPort();//日志输出代理IP和端口
        }
        #endregion


        #region 第一页按钮
        private void BtnAddRule_Click(object sender, EventArgs e)
        {
            IFiddlerEditForm AddRuleForm = new IFiddlerEditForm()
            {
                Text = "增加规则"
            };
            AddRuleForm.GiveRule += new IFiddlerEditForm.EventHandler(AddRule);//使用委托事件，取值增加规则
            AddRuleForm.CmbType.SelectedIndex = 0;//默认选中 发送数据
            //清空修改前、修改后、备注编辑框
            AddRuleForm.TxtMatch.Text = string.Empty;
            AddRuleForm.TxtReplace.Text = string.Empty;
            AddRuleForm.TxtComment.Text = string.Empty;
            //点击确定后的操作
            AddRuleForm.Show();
        }
        private void BtnEditRule_Click(object sender, EventArgs e)
        {
            if (LvRules.SelectedItems.Count > 0)
            {
                IFiddlerEditForm EditRuleForm = new IFiddlerEditForm()
                {
                    Text = "编辑规则"
                };
                EditRuleForm.GiveRule += new IFiddlerEditForm.EventHandler(EditRule);//使用委托事件，取值增加规则
                switch (LvRules.SelectedItems[0].SubItems[1].Text)
                {
                    case "发送数据":
                        EditRuleForm.CmbType.SelectedIndex = 0;
                        break;
                    case "返回数据":
                        EditRuleForm.CmbType.SelectedIndex = 1;
                        break;
                    case "网址":
                        EditRuleForm.CmbType.SelectedIndex = 2;
                        break;
                    case "COOKIE":
                        EditRuleForm.CmbType.SelectedIndex = 3;
                        break;
                    case "REFERER":
                        EditRuleForm.CmbType.SelectedIndex = 4;
                        break;
                    default:
                        EditRuleForm.CmbType.SelectedIndex = 0;
                        break;
                }
                //将选中规则填入编辑窗口相应位置处
                EditRuleForm.TxtMatch.Text = LvRules.SelectedItems[0].SubItems[2].Text;
                EditRuleForm.TxtReplace.Text = LvRules.SelectedItems[0].SubItems[3].Text;
                EditRuleForm.TxtComment.Text = LvRules.SelectedItems[0].SubItems[4].Text;
                EditRuleForm.Show();
            }
        }
        private void BtnDelRule_Click(object sender, EventArgs e)
        {
            for (int i = LvRules.SelectedItems.Count - 1; i >= 0; i--)
            {
                ListViewItem item = LvRules.SelectedItems[i];
                LvRules.Items.Remove(item);
                RefreshID();
                SaveRules();
            }
        }
        private void BtnUpRule_Click(object sender, EventArgs e)
        {
            ListViewUpMove();
            RefreshID();
            SaveRules();
        }
        private void BtnDownRule_Click(object sender, EventArgs e)
        {
            ListViewDownMove();
            RefreshID();
            SaveRules();
        }
        private void BtnClearRule_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("请再次确认是否删除所有的规则并保存 - 此操作无法恢复", "清空所有规则", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                LvRules.Items.Clear();//清空所有规则表项
                SaveRules();//保存清空后的表项
                LogMain("已清空所有规则!");
            }
        }
        #endregion
        #region 第三页按钮
        private void BtnLoadDefaultConfiguration_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("请再次确认是否删除所有的规则并还原设置 - 此操作无法恢复", "清空所有设置", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                LvRules.Items.Clear();//清空所有规则表项
                SaveRules();//保存清空后的表项
                LogMain("成功载入默认配置!");
            }
        }

        private void BtnGetLocalIP_Click(object sender, EventArgs e)
        {
            ShowLocalIpAndPort();
        }

        /// <summary>
        /// 显示本机IP及端口；
        /// </summary>
        private void ShowLocalIpAndPort()
        {
            string port = CONFIG.ListenPort.ToString();//获取Fiddler代理端口
            foreach (string ip in GetLocalIpv4())
            {
                string str = "代理地址:" + ip + ":" + port;
                LogMain(str);
            }
            return;
        }

        /// <summary>
        /// 排除Ipv6仅获取ipv4地址
        /// </summary>
        /// <returns></returns>
        private string[] GetLocalIpv4()
        {
            //事先不知道ip的个数，数组长度未知，因此用StringCollection储存  
            IPAddress[] localIPs;
            localIPs = Dns.GetHostAddresses(Dns.GetHostName());
            StringCollection IpCollection = new StringCollection();
            foreach (IPAddress ip in localIPs)
            {
                //根据AddressFamily判断是否为ipv4,如果是InterNetWorkV6则为ipv6  
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    IpCollection.Add(ip.ToString());
            }
            string[] IpArray = new string[IpCollection.Count];
            IpCollection.CopyTo(IpArray, 0);
            return IpArray;
        }
        #endregion

        #region iFiddler方法
        /// <summary>
        /// 自动修改规则
        /// </summary>
        /// <param name="oSession"></param>
        public void AutoRules(Session oSession)
        {
            AutoRuleHelper Autorule = new AutoRuleHelper();
            Autorule.AutoRule(oSession, LvRules);//自动修改规则
        }

        /// <summary>
        /// 自动取出Cookies
        /// </summary>
        /// <param name="oSession"></param>
        public void AutoGetCookies(Session oSession)
        {
            if (ChkGetCookies.Checked) //开启自动获取cookies
            {
                string url = TxtGetCookiesUrl.Text;  //取url值
                if (!string.IsNullOrEmpty(url)) //确保url不为空
                {
                    string Cookies = oSession.oRequest["Cookie"];
                    if (oSession.uriContains(url) && !string.IsNullOrEmpty(Cookies)) //符合url且cookies不为空
                    {
                        LogGetCookies(oSession.url, Cookies); //输出取出的cookies
                    }
                }
            }
        }

        /// <summary>
        /// 自动取出返回文本
        /// </summary>
        /// <param name="oSession"></param>
        public void AutoGetResponseText(Session oSession)
        {
            if (ChkGetResponseText.Checked)
            {
                string strLeft = TxtGetResponseTextLeft.Text;
                string strRight = TxtGetResponseTextRight.Text;
                string str = oSession.GetResponseBodyAsString();
                if (!string.IsNullOrEmpty(str) && !string.IsNullOrEmpty(strLeft) && !string.IsNullOrEmpty(strRight))//确保返回值、取出前、后不为空
                {
                    string StrBetween = GetStrBetween(str, strLeft, strRight);
                    if (!string.IsNullOrEmpty(StrBetween))
                    {
                        TxtGetResponseTextLog.AppendText(StrBetween + "\r\n");
                    }
                }
            }
        }


        #endregion


        #region Listview操作
        /// <summary>
        /// 上移Listview
        /// </summary>
        /// <param name="listView"></param>
        private void ListViewUpMove()
        {
            if (LvRules.SelectedItems.Count == 0)
            {
                return;
            }
            LvRules.BeginUpdate();
            if (LvRules.SelectedItems[0].Index > 0)
            {
                foreach (ListViewItem lvi in LvRules.SelectedItems)
                {
                    ListViewItem lviSelectedItem = lvi;
                    int indexSelectedItem = lvi.Index;
                    LvRules.Items.RemoveAt(indexSelectedItem);
                    LvRules.Items.Insert(indexSelectedItem - 1, lviSelectedItem);
                }
            }
            LvRules.EndUpdate();
            if (LvRules.Items.Count > 0 && LvRules.SelectedItems.Count > 0)
            {
                LvRules.Focus();
                LvRules.SelectedItems[0].Focused = true;
                LvRules.SelectedItems[0].EnsureVisible();
            }
        }

        /// <summary>
        /// 刷新Listview的序号
        /// </summary>
        /// <param name="Lv"></param>
        private void RefreshID()
        {
            for (int i = 0; i < LvRules.Items.Count; i++)
            {
                LvRules.Items[i].Text = (i + 1).ToString();
            }
        }

        /// <summary>
        /// 下移Listview
        /// </summary>
        /// <param name="listView"></param>
        private void ListViewDownMove()
        {
            if (LvRules.SelectedItems.Count == 0)
            {
                return;
            }
            LvRules.BeginUpdate();
            int indexMaxSelectedItem = LvRules.SelectedItems[LvRules.SelectedItems.Count - 1].Index;
            if (indexMaxSelectedItem < LvRules.Items.Count - 1)
            {
                for (int i = LvRules.SelectedItems.Count - 1; i >= 0; i--)
                {
                    ListViewItem lviSelectedItem = LvRules.SelectedItems[i];
                    int indexSelectedItem = lviSelectedItem.Index;
                    LvRules.Items.RemoveAt(indexSelectedItem);
                    LvRules.Items.Insert(indexSelectedItem + 1, lviSelectedItem);
                }
            }
            LvRules.EndUpdate();
            if (LvRules.Items.Count > 0 && LvRules.SelectedItems.Count > 0)
            {
                LvRules.Focus();
                LvRules.SelectedItems[LvRules.SelectedItems.Count - 1].Focused = true;
                LvRules.SelectedItems[LvRules.SelectedItems.Count - 1].EnsureVisible();
            }
        }

        /// <summary>
        /// 增加规则
        /// </summary>
        /// <param name="type"></param>
        /// <param name="match"></param>
        /// <param name="replace"></param>
        /// <param name="comment"></param>
        public void AddRule(string type, string match, string replace, string comment)
        {
            try
            {
                ListViewItem item = new ListViewItem();
                item.SubItems.Add(type);
                item.SubItems.Add(match);
                item.SubItems.Add(replace);
                item.SubItems.Add(comment);
                LvRules.Items.Add(item);
                item.Checked = true;
                RefreshID();//重新排序
                SaveRules();//保存规则
        }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        /// <summary>
        /// 编辑规则
        /// </summary>
        /// <param name="type"></param>
        /// <param name="match"></param>
        /// <param name="replace"></param>
        /// <param name="comment"></param>
        public void EditRule(string type, string match, string replace, string comment)
        {
               //点击确定后修改相应选中规则
                LvRules.SelectedItems[0].SubItems[1].Text = type;
                LvRules.SelectedItems[0].SubItems[2].Text = match;
                LvRules.SelectedItems[0].SubItems[3].Text = replace;
                LvRules.SelectedItems[0].SubItems[4].Text = comment;
                RefreshID();//重新排序
                SaveRules();//保存规则
        }

        /// <summary>
        /// 保存规则
        /// </summary>
        public void SaveRules()
        {
            try
            {
                //实例化xml文档
                XmlDocument xmlDoc = new XmlDocument();
                XmlDeclaration xmlDeclar;
                xmlDeclar = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xmlDoc.AppendChild(xmlDeclar);
                //实例化一个根节点
                XmlElement root = xmlDoc.CreateElement("iFiddlerRules");
                //把根节点添加到xml文档中
                xmlDoc.AppendChild(root);
                for (int i = 0; i != LvRules.Items.Count; i++)
                {
                    string id = LvRules.Items[i].SubItems[0].Text;
                    string type = LvRules.Items[i].SubItems[1].Text;
                    string match = LvRules.Items[i].SubItems[2].Text;
                    string replace = LvRules.Items[i].SubItems[3].Text;
                    string comment = LvRules.Items[i].SubItems[4].Text;
                    XmlElement iRule = xmlDoc.CreateElement("Rule");
                    iRule.SetAttribute("id", id);
                    root.AppendChild(iRule);
                    XmlElement xType = xmlDoc.CreateElement("Type");
                    xType.InnerText = type;
                    iRule.AppendChild(xType);
                    XmlElement xMatch = xmlDoc.CreateElement("Match");
                    xMatch.InnerText = match;
                    iRule.AppendChild(xMatch);
                    XmlElement xReplace = xmlDoc.CreateElement("Replace");
                    xReplace.InnerText = replace;
                    iRule.AppendChild(xReplace);
                    XmlElement xComment = xmlDoc.CreateElement("Comment");
                    xComment.InnerText = comment;
                    iRule.AppendChild(xComment);
                }
                xmlDoc.Save(IRabbit.Path);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        /// <summary>
        /// 加载规则
        /// </summary>
        public void LoadRules()
        {
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(IRabbit.Path);
                XmlNodeList _List = xmlDoc.SelectSingleNode("iFiddlerRules").ChildNodes;
                foreach (XmlNode xn in _List)//遍历所有子节点 
                {
                    XmlElement xe = (XmlElement)xn;//转换为元素
                    ListViewItem i_item = LvRules.Items.Add(xe.GetAttribute("Rule"));
                    i_item.Text = xe.GetAttribute("id");
                    i_item.SubItems.Add(xe.GetElementsByTagName("Type").Item(0).InnerText);
                    i_item.SubItems.Add(xe.GetElementsByTagName("Match").Item(0).InnerText);
                    i_item.SubItems.Add(xe.GetElementsByTagName("Replace").Item(0).InnerText);
                    i_item.SubItems.Add(xe.GetElementsByTagName("Comment").Item(0).InnerText);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
        #endregion

        #region Utils
        /// <summary>
        /// 取字符串中间文本
        /// </summary>
        /// <param name="str">总字符串</param>
        /// <param name="strLeft">左边字符串</param>
        /// <param name="strRight">右边字符串</param>
        /// <returns>中间字符串</returns>
        private string GetStrBetween(string str, string strLeft, string strRight)
        {
            int leftlocation;//左边位置
            int rightlocation;//右边位置
            int strmidlength; ;//中间字符串长度
            string strmid;//中间字符串 
            leftlocation = str.IndexOf(strLeft);//获取左边字符串头所在位置
            if (leftlocation == -1)//判断左边字符串是否存在于总字符串中
            {
                return string.Empty;
            }
            leftlocation = leftlocation + strLeft.Length;//获取左边字符串尾所在位置 
            rightlocation = str.IndexOf(strRight, leftlocation);//获取右边字符串头所在位置
            if (rightlocation == -1 || leftlocation > rightlocation)//判断右边字符串是否存在于总字符串中，左边字符串位置是否在右边字符串前
            {
                return string.Empty;
            }
            strmidlength = rightlocation - leftlocation;//计算中间字符串长度 
            strmid = str.Substring(leftlocation, strmidlength);//取出中间字符串 
            return strmid;//返回中间字符串
        }

        /// <summary>
        /// 正则替换发送值
        /// </summary>
        /// <param name="oSession"></param>
        /// <param name="match"></param>
        /// <param name="replace"></param>
        private void RegexReplacePost(Session oSession, string match, string replace)
        {
            var strBody = oSession.GetRequestBodyAsString();
            strBody = Regex.Replace(strBody, match, replace);
            oSession.utilSetRequestBody(strBody);
        }
        #endregion

        #region 日志输出操作
        /// <summary>
        /// 主日志输出
        /// </summary>
        /// <param name="log"></param>
        private delegate void Delegate_LogMain(string log);//定义主日志输出委托
        public void LogMain(string log)
        {
            if (!TxtMainLog.InvokeRequired)
            {
                TxtMainLog.AppendText(DateTime.Now.ToString("HH:mm:ss   ") + log + "\r\n");
            }
            else
            {
                Delegate_LogMain delgate_logmain = new Delegate_LogMain(LogMain);
                TxtMainLog.Invoke(delgate_logmain, log);
            }
        }

        /// <summary>
        /// 获取Cookies日志输出
        /// </summary>
        /// <param name="url"></param>
        /// <param name="cookies"></param>
        private delegate void Delgate_LogGetCookies(string url, string cookies);
        public void LogGetCookies(string url, string cookies)
        {
            if (!TxtGetCookiesLog.InvokeRequired)
            {
                if (!TxtGetCookiesLog.Text.Contains(cookies))
                {
                    TxtGetCookiesLog.AppendText("网址:\r\n" + url + "\r\n---------------------------------------------------------------------\r\nCookies:\r\n" + cookies + "\r\n======================================\r\n");
                }
            }
            else
            {
                Delgate_LogGetCookies delgate_loggetcookies = new Delgate_LogGetCookies(LogGetCookies);
                TxtGetCookiesLog.Invoke(delgate_loggetcookies, url, cookies);
            }

        }

        /// <summary>
        /// 取出返回文本日志输出
        /// </summary>
        /// <param name="log"></param>
        private delegate void Delegate_LogGetResponseTextLog(string log);
        public void LogGetResponseTextLog(string log)
        {
            if (!TxtGetResponseTextLog.InvokeRequired)
            {
                TxtGetResponseTextLog.AppendText(log + "\r\n");
            }
            else
            {
                Delegate_LogGetResponseTextLog delgate_loggetresponsetextlog = new Delegate_LogGetResponseTextLog(LogGetResponseTextLog);
                TxtGetResponseTextLog.Invoke(delgate_loggetresponsetextlog, log);
            }
        }
        #endregion

    }
}
